/**
 * https://www.cnblogs.com/zhaowinter/p/10776868.html
 * @type {{debug_mode?: boolean, createClient?, RedisClient?: function(*=, *=): void, print?: function(*=, *): void, Multi?: function(*, *=): void, AbortError?: function(*=, *=): void, RedisError?: *, ParserError?: *, ReplyError?: *, AggregateError?: function(*=): void, addCommand?: function(*=): void, add_command?: function(*=): void, debugMode?}}
 */
const redis = require('redis');
const redisScan = require('node-redis-scan');
const config = require('../config/config')
client = redis.createClient(config.redis.port, config.redis.host, config.redis.options);
const scanner = new redisScan(client);

client.on('error', function (err) {
    console.log(err);
});

client.on('connect', function () {
    console.log('redis connect success!');
});

function Cache() {
}

let text = async (key) => {
    let doc = await new Promise((resolve) => {
        client.get(key, function (err, res) {
            return resolve(res);
        });
    });
    return JSON.parse(doc);
};

/**
 *
 * @param key key
 * @param value value
 * @param expire 过期时间，秒
 * @returns {*}
 */
Cache.set = async function (key, value, expire) {
    expire = expire || config.redis.expire;
    // 缓存有效期不可低于 1 小时（3600秒）
    expire = expire < 3600 ? 3600 : expire
    value = JSON.stringify(value);
    return await client.set(key, value, function (err) {
        if (err) {
            console.error(err);
        } else {
            client.expire(key, expire);
        }

    });
};

/**
 * 无序集合 set 的操作，只能用于 trend 统计（放开 expire 限制）
 * @param key key
 * @param value value
 * @param expire 过期时间，秒
 * @returns {*}
 */
Cache.sadd = async function (key, value, expire) {
    value = JSON.stringify(value);
    return await client.sadd(key, value, function (err, response) {
        if (err) {
            console.error(err, response);
        } else {
            if (expire) {
                client.expire(key, expire);
            }
        }

    });
};

/**
 * 返回集合 key 的基数(集合中元素的数量)。
 * @param key
 */
Cache.scard = async function (key) {
    return await new Promise((resolve) => {
        client.scard(key, function (err, res) {
            return resolve(res);
        });
    });
};

/**
 * 返回集合中的所有的成员
 * @param key
 */
Cache.smembers = async function (key) {
    const list = await new Promise((resolve) => {
        client.smembers(key, function (err, res) {
            return resolve(res);
        });
    });
    if (list) {
        const result = [];
        list.forEach(function (item) {
            result.push(JSON.parse(item))
        })
        return result;
    }
    return [];
};

/**
 * 哈希，只能用于 trend 统计（放开 expire 限制）
 *
 * @param key key
 * @param itemKey item 对象的key
 * @param itemValue item 对象的value
 * @param expire 过期时间，秒
 * @returns {*}
 */
Cache.hset = function (key, itemKey, itemValue, expire) {
    client.hset(key, itemKey, itemValue, function (err, response) {
        if (err) {
            console.error(err, response);
        } else {
            if (expire) {
                client.expire(key, expire);
            }
        }
    });
};

/**
 * hash 表中所有内容
 * @param key
 */
Cache.hgetall = async function (key) {
    return await new Promise((resolve) => {
        client.hgetall(key, function (err, res) {
            return resolve(res);
        });
    });
};

/**
 * hash 表中单个内容
 * @param key hash 表的key
 * @param itemKey hash 表中单个元素的 key
 */
Cache.hget = async function (key, itemKey) {
    return await new Promise((resolve) => {
        client.hget(key, itemKey, function (err, res) {
            return resolve(res);
        });
    });
};

/**
 * matchingKeys will be an array of strings if matches were found otherwise it will be an empty array.
 * @param key prefix
 */
Cache.scan = async function (key) {
    return await new Promise((resolve) => {
        scanner.scan(key + '*', function (err, matchingKeys) {
            return resolve(matchingKeys);
        });
    });
};

Cache.get = async (key) => {
    return await text(key);
};

/**
 * 按照 Key ，实现 value 自增
 * @param key
 * @param callback callback(err, key)
 */
Cache.incr = function (key, callback) {
    client.incr(key, callback);
};

Cache.del = async function (key) {
    return await client.del(key, function (err, reply) {
        if (err) {
            console.error(err);
        }
    });
};

module.exports = Cache;